/*
 * Copyright 2007 National Bioinformatics Network
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dgbgui.gui.widgets;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.geom.Point2D;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.util.PBounds;

@SuppressWarnings("serial")
public class Widget extends PNode {

    public Widget(PNode parent) {
        m_parent = parent;
        // Add this Widget2 to the parent Widget2 (using the GObject methods)
        if ( parent != null ) {
            parent.addChild(this);
        }
    }

    
    /**
     * @return the current size of the Widget2
     */
    public Point2D.Double getSize() {
        PBounds bounds = getFullBounds();
        return new Point2D.Double(bounds.width,bounds.height);
            
    }

    /**
     * @return the stroke colour of this widget
     */
    public Color getStrokeColour() {
        // Find the first parent with a stroke colour set, otherwise
        // return the default
        Widget testWidget = this;
        while ( testWidget != null ) {
            // Return the first stroke colour that was found in the
            // hierarchy
            if ( testWidget.m_strokeColour != null ) {
                return testWidget.m_strokeColour;
            }
            // Navigate up the hiertarcy while the parents are Widgets
            if ( ( testWidget.getParent() != null ) && ( testWidget.getParent() instanceof Widget ) ) {
                testWidget = (Widget)testWidget.getParent();
            } else {
                testWidget = null;
            }
        }
        return getDefaultStrokeColour();
    }
    
    /**
     * @return the stroke style of this widget
     */
    public BasicStroke getStrokeStyle() {
        // Find the first parent with a stroke colour set, otherwise
        // return the default
        Widget testWidget = this;
        while ( testWidget != null ) {
            // Return the first stroke colour that was found in the
            // hierarchy
            if ( testWidget.m_strokeStyle != null ) {
                return testWidget.m_strokeStyle;
            }
            // Navigate up the hiertarcy while the parents are Widgets
            if ( ( testWidget.getParent() != null ) && ( testWidget.getParent() instanceof Widget ) ) {
                testWidget = (Widget)testWidget.getParent();
            } else {
                testWidget = null;
            }
        }
        return getDefaultStrokeStyle();
    }
    
    /**
     * @return the fill colour if this widget
     */
    public Color getFillColour() {
        //  Find the first parent with a fill colour set, otherwise
        // return the default
        Widget testWidget = this;
        while ( testWidget != null ) {
            // Return the first fill colour that was found in the
            // hierarchy
            if ( testWidget.m_fillColour != null ) {
                return testWidget.m_fillColour;
            }
            // Navigate up the hiertarcy while the parents are Widgets
            testWidget = testWidget.getNextWidgetParent();

        }
        return getDefaultFillColour();
    }
    
    /**
     * @return The first parent widget of the class type specified
     */
    public Widget getParentOfClass(Class requiredClass) {
        // Navigate up the hiertarcy while the parents are Widgets
        Widget testWidget = this;
        while ( testWidget != null ) {
            if ( requiredClass.isInstance(testWidget) ) {
                return (Widget)testWidget;
            }
            testWidget = testWidget.getNextWidgetParent();
        }
        return null;
    }
    
    
    /**
     * Find a preferred widget from a collection of widgets
     * @param objects
     * @return The preferred widget
     */
    public static Widget findPreferencialObject(Collection objects,LinkedHashSet<Class>  objectPreference) {
        // For each preference, check the objects if they are
        // of that class.
        for ( Class classType : objectPreference ) {
            for ( Object obj : objects ) {
               if ( classType.isInstance(obj) && (obj instanceof Widget) ) {
                   return (Widget)obj;
               }
            }
        }
        return null;
    }
    
    /**
     * Find a list of preferred widgets from a collection of widgets
     * @param objects
     * @return The preferred widget
     */
    public static Set<Widget> findPreferencialObjects(Collection objects,LinkedHashSet<Class>  objectPreference) {
        // For each preference, check the objects if they are
        // of that class.
        Set<Widget> widgets = new HashSet<Widget>();
        for ( Class classType : objectPreference ) {
            for ( Object obj : objects ) {
               if ( classType.isInstance(obj) && (obj instanceof Widget) ) {
                   widgets.add((Widget)obj);
               }
            }
            if ( widgets.size() > 0 ) {
                return widgets;
            }
        }
        return widgets;
    }
    
    /**
     * @return The next parent Widget, null if no parent or parent not a Widget
     */
    private Widget getNextWidgetParent() {
        if ( ( getParent() != null ) && ( getParent() instanceof Widget ) ) {
            return (Widget)getParent();
        } else {
            return null;
        }
    }
    
    /**
     * @return The widget's own fill colour, not using the hierarchy
     */
    public Color getOwnFillColour() {
        return m_fillColour;
    }
    
    /**
     * @return The widget's own stroke colour, not using the hierarchy
     */
    public Color getOwnStrokeColour() {
        return m_strokeColour;
    }
    
    /**
     * @return the default stroke colour
     */
    static public Color getDefaultStrokeColour() {
        return Color.black;
    }
    
    /**
     * @return the default stroke style
     */
    static public BasicStroke getDefaultStrokeStyle() {
        return new BasicStroke();
    }
    
    /**
     * @return the default fill colour
     */
    static public Color getDefaultFillColour() {
        return new Color(240,240,250,100);
    }
    
    
    /**
     * Set the widget's stroke colour
     */
    public void setStrokeColor(Color color) {
        m_strokeColour = color;
    }
    
    /**
     * Set the widgets's stroke style
     */
    public void setStrokeStyle(BasicStroke stroke) {
        m_strokeStyle = stroke;
    }
    
    /**
     * Set the widget's fill colour
     */
    public void setFillColor(Color color) {
        m_fillColour = color;
    }
    
    
    /// The paint and stroke colours, null by default
    Color m_fillColour;
    Color m_strokeColour;
    BasicStroke m_strokeStyle;
    
    //public abstract void setSize(Point2D.Double m_size);
    
    protected PNode m_parent;



}

